﻿// #pragma execution_character_set("utf-8")
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <direct.h>
#include <fstream>
#include <vector>
#include <algorithm>
#include <io.h>
#include <sstream>
#include <string>
#include <regex>
using namespace std;
class _FileExt
{
public:
    string fullname;  //绝对路径
    string filename;  //文件名(不含扩展名)
    string extension; //扩展名
    string filepath;  //绝对路径(不含文件名)
    int version;      //数字扩展名

public:
    _FileExt(const char *file);
};
//清理小版本
void MyPurge(const char *path);
//根据类型获取目录下所有文件
void ListFileByType(const char *path, const char *match, vector<_FileExt> &files);
int str2int(const std::string istr);
bool sortbyname(const _FileExt &t1, const _FileExt &t2);

_FileExt::_FileExt(const char *file)
{
    smatch result;
    fullname.assign(file);
    //匹配目录 含结尾'/'
    regex_search(fullname, result, regex(".*[\\\\/]"))
        ? filepath = result.begin()->str()
        : filepath = string();
    //匹配文件名 不含扩展名
    regex_search(fullname, result, regex("^.+[\\\\/](.*?)\\..*?$"))
        ? filename = result[1].str()
        : filename = string();
    //匹配扩展名
    regex_search(fullname, result, regex("^.+\\.(.*?)$"))
        ? extension = result[1].str()
        : extension = string();
    //匹配数字扩展名
    regex_search(fullname, result, regex("^.+\\.(\\d*?)$"))
        ? version = str2int(result[1].str())
        : version = -1;
}

int main(int argc, char **argv)
{
#ifdef UNICODE
    cout << "#define UNICODE";
#endif
    // system("chcp 65001");
    char *path;
    // setlocale(LC_ALL, "Chinese-simplified");
    switch (argc)
    {
    case 1:
        if ((path = getcwd(NULL, 0)) == NULL)
        {
            cout << "当前目录获取失败！" << endl;
            return 0;
        }
        break;
    case 2:
        path = argv[1];
        break;
    default:
        cout << "传入的参数不正确！" << endl;
        break;
    }

    cout << "正在清理目录:" << path << endl;
    MyPurge(path);
    system("pause");
    return 0;
}

//根据类型获取目录下所有文件
void ListFileByType(const char *path, const char *match, vector<_FileExt> &files)
{
    //文件句柄
    intptr_t hFile = 0;
    //文件信息
    struct _finddata64i32_t fileinfo; //包含中文目录，使用宽字符
    string p;
    if ((hFile = _findfirst(p.assign(path).append("\\").append(match).c_str(), &fileinfo)) != -1) //查找目录下文件，并将信息存入fileinfo
    {
        do
        {
            //排除目录
            if (strcmp(fileinfo.name, ".") == 0 || strcmp(fileinfo.name, "..") == 0)
                continue;
            p.assign(path).append("\\").append(fileinfo.name);
            _FileExt file(p.c_str());
            files.push_back(file); //_FileExt自建类，包含绝对路径和扩展名
        } while (_findnext(hFile, &fileinfo) == 0);
        _findclose(hFile);
    }
    sort(files.begin(), files.end(), sortbyname);
}
//清理小版本
void MyPurge(const char *path)
{
    vector<_FileExt> files;
    ListFileByType(path, "*", files);
    for (vector<_FileExt>::iterator it = files.begin(); it != files.end();)
    {
        try
        {
            _FileExt f1 = *it;
            _FileExt f2 = *(it + 1);
            int e1 = f1.version;
            int e2 = f2.version;
            //判断后缀是否为数字，如果不是数字，str2int()返回0
            if (e1 == -1)
            {
                it = files.erase(it);
                continue; //防止出现连续连个后缀不为数字的文件
            }

            else if ((it + 1) != files.end() && e2 == -1)
            {
                it = files.erase(it + 1);
                continue;
            }
            else
            {

                if (strcmp(f1.filename.c_str(), f2.filename.c_str()) == 0) //判断文件名相同
                {
                    string file1 = f1.fullname;
                    string file2 = f2.fullname;
                    //删除低版本文件，并将指针回退
                    if (e2 > e1)
                    {
                        DeleteFileA(file1.c_str());
                        cout << "del " << f1.filename << "." << f1.extension << endl;
                        it = files.erase(it);
                    }
                    else
                    {
                        DeleteFileA(file2.c_str());
                        cout << "del " << f2.filename << "." << f2.extension << endl;
                        files.erase(it + 1);
                    }
                }
                else
                    it++;
            }
        }
        catch (exception e)
        {
            cout << "purge error:" << e.what();
        }
    }
    for (vector<_FileExt>::iterator it = files.begin(); it != files.end(); it++)
    {
        _FileExt file = *it;
        if (file.version > 1)
        {
            string newname = file.filepath + file.filename + ".1";
            string oldname = file.fullname;
            if (rename(oldname.c_str(), newname.c_str()) == -1)
                cout << "rename " << file.filename << "errno:" << errno;
            else
                cout << "rename  " << file.filename << "." << file.extension << " "
                     << file.filename << ".1" << endl;
        }
    }
}
//string->int
int str2int(const string istr)
{
    istringstream ss;
    ss.str(istr);
    int ret = 0;
    ss >> ret;
    return ret;
}
//文件排序
bool sortbyname(const _FileExt &t1, const _FileExt &t2)
{
    // if (strcmp(t1.filename.c_str(), t2.filename.c_str()) < 0)
    //     return true;
    // else
    //     return false;
    return t1.filename < t2.filename; //升序排列
}